package com.beerandjesus.blackjack.ui;

import com.beerandjesus.blackjack.controller.GameController;
import com.beerandjesus.blackjack.controller.HandController;
import com.beerandjesus.blackjack.deck.Card;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;

public class BlackjackZork {
    private BufferedReader in;
    private GameController controller;

    public static void main(String[] args) {
        BlackjackZork zork = new BlackjackZork();
        zork.greet();
        zork.play();
    }

    public BlackjackZork() {
        controller = new GameController(new ZorkCardDisplayer(),
                new ZorkGameEventDisplayer());
    }

    private void play() {
        say("");
        controller.refreshForNewDeal();
        controller.dealToPlayer();
        controller.dealToDealer();
        controller.dealToPlayer();
        controller.dealToDealer();
        checkStatus();
    }

    private void checkStatus() {
        if (isGameOver()) {
            play();
        } else {
            getCommand();
        }
    }

    private boolean isGameOver() {
        return controller.isPlayerWin() ||
                controller.isDealerWin() ||
                controller.isPush();
    }

    private void getCommand() {
        say("");
        say("What would you like to do? [ h, s or q ]");
        String cmd = listen();
        say("");
        processCommand(cmd);
    }

    private void processCommand(String cmd) {
        if (cmd.equals("h")) {
            hitPlayerAndListen();
        } else if (cmd.equals("s")) {
            controller.playOutDealer();
            play();
        } else if (cmd.equals("q")) {
            quit();
        } else {
            say("I don't know what '" + cmd + "' means");
            getCommand();
        }
    }

    private void showDealerCards() {
        say("");
        say("Dealer has:");
        Iterator hand = controller.getDealerHand().iterator();
        while (hand.hasNext()) {
            Card card = (Card) hand.next();
            System.out.println(card.getDisplayString());
        }
        System.out.println("... for a total of: " + controller.getDealerHand().count());
    }

    private void hitPlayerAndListen() {
        controller.dealToPlayer();
        if (controller.getPlayerHand().canPlay()) {
            getCommand();
        } else if (isGameOver()) {
            play();
        } else {
            controller.playOutDealer();
            play();
        }
    }

    private void printRules() {
        say("");
        say("Commands are:");
        say("    h    Hit me");
        say("    s    Stay");
        say("    q    Quit");
        say("");
    }

    private void greet() {
        in = new BufferedReader(new InputStreamReader(System.in));
        say("What is your name?");
        String player = listen();
        say("Welcome " + player + "! Are you ready to play some blackjack?");
        String answer = listen();
        if (answer.equalsIgnoreCase("yes") || answer.equalsIgnoreCase("y")) {
            say("Great! Let's play.");
        } else {
            say("Ok! Bye!");
            quit();
        }
        printRules();
    }

    private void quit() {
        say("Quitting...");
        System.exit(0);
    }

    private String listen() {
        String input = null;
        System.out.print("> ");
        try {
            input = in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        return input;
    }

    private void say(String msg) {
        System.out.println(msg);
    }

    public class ZorkCardDisplayer implements CardDisplayer {

        public void displayCards(HandController handController) {
            if (handController.isDealer()) {
                if (handController.size() == 2) {
                    Card card = handController.getLastCardDealt();
                    say("Dealer is showing a: " + card.getDisplayString());
                }
            } else {
                Card card = handController.getLastCardDealt();
                say("Dealer gives you: " + card.getDisplayString());
            }
        }
    }

    public class ZorkGameEventDisplayer implements GameEventDisplayer {

        public void displayPlayerBlackjack() {
            say("**** Player BLACKJACK!! ****");
        }

        public void displayPlayerBust() {
            say("You have " + controller.getPlayerHand().count());
            say("---- Player BUSTED!! ----");
        }

        public void displayDealerBlackjack() {
            say("---- Dealer BLACKJACK!! ----");
        }

        public void displayDealerBust() {
            say("**** Dealer BUSTED!! ****");
        }

        public void displayPush() {
            showDealerCards();
            say("++++ PUSH ++++");
        }

        public void displayPlayerWin() {
            if (!controller.getPlayerHand().isBlackjack())
                showDealerCards();
            say("**** You WON! ****");
        }

        public void displayDealerWin() {
            if (!controller.getDealerHand().isBlackjack())
                showDealerCards();
            say("---- Sorry, you lost. ----");
        }
    }


}
